#include "action_comb.h"
#include <wx/dcmemory.h>
#include <wx/dcclient.h>
wxBEGIN_EVENT_TABLE(ActionCombination, wxPanel)
        EVT_TIMER(-1, ActionCombination::OnTimer)
		EVT_CHAR_HOOK(ActionCombination::OnKeyDown)
wxEND_EVENT_TABLE()

ActionCombination::ActionCombination(wxWindow* parent,wxWindowID id,const wxPoint& pos,const wxSize& size)
{
	m_drag = false;
	Create(parent, id, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _T("id"));
	Connect(wxEVT_PAINT,(wxObjectEventFunction)&ActionCombination::OnPaint);
	Connect(wxEVT_ERASE_BACKGROUND,(wxObjectEventFunction)&ActionCombination::OnBackground);
	Connect(wxEVT_LEFT_DOWN,(wxObjectEventFunction)&ActionCombination::LeftDown);
	Connect(wxEVT_RIGHT_DOWN,(wxObjectEventFunction)&ActionCombination::RightDown);
	Connect(wxEVT_LEFT_UP,(wxObjectEventFunction)&ActionCombination::LeftUp);
	Connect(wxEVT_MOTION,(wxObjectEventFunction)&ActionCombination::MouseMove);

	//m_timer.SetOwner(this);
	//m_timer.Start(100);
}

ActionCombination::~ActionCombination()
{
}

void ActionCombination::OnTimer(wxTimerEvent &event)
{
	Refresh();
	NextFrame();
}

void ActionCombination::DrawAction(wxDC &dc,SActionInfo &action,bool select)
{
	if((action.type == EATSimple) && (action.simple.imageName.Len() > 0))
	{
		wxSize size = GetImageSize(action.simple.imageName);
		if(m_curFrame >= (size_t)action.simple.frameNum)
			m_curFrame = 0;
		wxRect rect;
		rect.x = size.GetWidth()/action.simple.frameNum*m_curFrame;
		rect.y = 0;
		rect.SetWidth(size.GetWidth()/action.simple.frameNum);
		rect.SetHeight(size.GetHeight());
		DrawImage(dc,action.simple.imageName,&rect,action.x,action.y);
		if(select)
		{
			rect = GetActionRect(action);
			dc.SetBrush(*wxTRANSPARENT_BRUSH);
			dc.SetPen(*wxRED_PEN);
			dc.DrawRectangle(rect);
		}
			
	}
	else if(action.type == EATComplex)
	{
		if(m_curFrame >= action.complex.layerList.size())
			m_curFrame = 0;
		if(action.complex.layerList.size() > 0)
		{
			SLayer &layer = action.complex.layerList[m_curFrame];
			DrawImage(dc,layer.image.name,&(layer.image.rect),layer.x+action.x,layer.y+action.y);
			if(select)
			{
				dc.SetBrush(*wxTRANSPARENT_BRUSH);
				dc.SetPen(*wxRED_PEN);
				wxRect rect = GetActionRect(action);
				dc.DrawRectangle(rect);
			}
		}
	}
}

void ActionCombination::Draw(wxDC &dc)
{
	wxSize size = GetClientSize();
	dc.SetBrush(*wxWHITE_BRUSH);
	dc.DrawRectangle(size);
	
	for(size_t i = 0; i < m_actionList.size(); i++)
	{
		DrawAction(dc,m_actionList[i],m_selAction == i);
	}
	SActionInfo *pAction = GetSelAction();
	if(pAction != NULL)
	{
		DrawAction(dc,*pAction,false);
	}
}

void ActionCombination::OnPaint(wxPaintEvent& event)
{
	wxPaintDC dc(this);

    wxSize clientSize = GetClientSize();
    wxBitmap bmp(clientSize.GetWidth(),clientSize.GetHeight());
    wxMemoryDC memDC(bmp);
	//memDC.DrawRectangle(clientSize);
    Draw(memDC);
    
    dc.Blit(0,0,clientSize.GetWidth(),clientSize.GetHeight(),&memDC,0,0);
}

void ActionCombination::OnBackground(wxEraseEvent &event)
{
}

void ActionCombination::RightDown(wxMouseEvent &event)
{
	SetSelAction(NULL);
	if(!m_timer.IsRunning())
		Refresh();
}

void ActionCombination::LeftDown(wxMouseEvent &event)
{
	event.Skip();
	int x = event.GetX();
    int y = event.GetY();
	SActionInfo *pAction = GetSelAction();
	if(pAction != NULL)
	{
		pAction->x = x;
		pAction->y = y;
		AddAction(*pAction);
		SetSelAction(NULL);
		return;
	}
	m_mouseX = x;
	m_mouseY = y;
	m_drag = true;
	if(m_actionList.size() <= 0)
		return;
	for(int i = (int)(m_actionList.size() - 1); i >= 0; i--)
	{
		wxRect rect = GetActionRect(m_actionList[i]);
		if(InRect(x,y,rect))
		{
			m_selAction = i;
			Refresh();
			return;
		}
	}
	m_selAction = -1;
}
void ActionCombination::LeftUp(wxMouseEvent &event)
{
	m_drag = false;
}
void ActionCombination::MoveSelect(int moveX,int moveY)
{
	if(m_selAction >= m_actionList.size())
		return;
	wxSize clientSize = GetClientSize();
	int moveToX = m_actionList[m_selAction].x + moveX;
	int moveToY = m_actionList[m_selAction].y + moveY;
	if((moveToX < 0) || (moveToY > clientSize.GetWidth()) || (moveToY < 0) || (moveToY > clientSize.GetHeight()))
		return;
	m_actionList[m_selAction].x = moveToX;
	m_actionList[m_selAction].y = moveToY;
	if(!m_timer.IsRunning())
		Refresh();
}

void ActionCombination::MouseMove(wxMouseEvent &event)
{
	int x = event.GetX();
    int y = event.GetY();
	SActionInfo *pAction = GetSelAction();
	if(pAction != NULL)
	{
		pAction->x = x;
		pAction->y = y;
		if(!m_timer.IsRunning())
			Refresh();
	}
	else if(m_drag)
	{
		int moveX = x - m_mouseX;
        int moveY = y - m_mouseY;
        MoveSelect(moveX,moveY);
        m_mouseX = x;
        m_mouseY = y;
	}
}

void ActionCombination::AddAction(SActionInfo &action)
{
	m_selAction = m_actionList.size();
	m_actionList.push_back(action);
	if(!m_timer.IsRunning())
		Refresh();
}

bool ActionCombination::Start()
{
	if(m_actionList.size() <= 0)
		return false;

	int timerSpace = 100;
	SActionInfo &action = m_actionList[0];
	if(action.type == EATSimple)
	{
		timerSpace = action.simple.frameSpace;
	}
	else if(action.type == EATComplex)
	{
		timerSpace = action.complex.frameSpace;
	}
	if(m_timer.IsRunning())
		m_timer.Stop();
	m_timer.Stop();
	m_timer.SetOwner(this);
	m_timer.Start(timerSpace);
	return true;
}

void ActionCombination::Stop()
{
	m_timer.Stop();
}
void ActionCombination::ClearAction()
{
}
void ActionCombination::OnKeyDown(wxKeyEvent& event)
{
	int keyCode = event.GetKeyCode();
	if(keyCode == WXK_LEFT)
		MoveSelect(-1,0);
	else if(keyCode == WXK_UP)
		MoveSelect(0,-1);
	else if(keyCode == WXK_RIGHT)
		MoveSelect(1,0);
	else if(keyCode == WXK_DOWN)
		MoveSelect(0,1);
	else if(keyCode == WXK_TAB)
	{
		m_selAction++;
		if(m_selAction >= m_actionList.size())
			m_selAction = 0;
		Refresh();
	}
	else if(keyCode == WXK_DELETE)
	{
		if(m_selAction < m_actionList.size())
		{
			m_actionList.erase(m_actionList.begin()+m_selAction);
			if(!m_timer.IsRunning())
				Refresh();
		}
	}
}